// MobileAltimeter.cpp : Defines the entry point for the application.
//

#include <windows.h>
#include <aygshell.h>

#include "MobileAltimeter.h"
#include "GPS.h"

// Message handler for Mobile Altimeter dialog.
INT_PTR CALLBACK MobileAltimeterDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_INITDIALOG:
			{
                // Create a Done button and size it.  
                SHINITDLGINFO shidi;
				SHMENUBARINFO mbi;

                shidi.dwMask = SHIDIM_FLAGS;
                shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN;
                shidi.hDlg = hDlg;
                SHInitDialog(&shidi);

				// Create a menu bar
                memset(&mbi, 0, sizeof(SHMENUBARINFO));
				mbi.cbSize     = sizeof(SHMENUBARINFO);
				mbi.hwndParent = hDlg;
				mbi.nToolBarId = IDR_MENU;
				mbi.hInstRes   = GetModuleHandle(NULL);
				mbi.dwFlags = SHCMBF_HMENU;
	            SHCreateMenuBar(&mbi);

				// Change the font of the main
				// altimeter reading
				LOGFONT lf;
				memset(&lf, 0, sizeof(LOGFONT));
				HDC hdc = GetDC(NULL);
				_tcscpy(lf.lfFaceName, _T("Tahoma"));
				lf.lfHeight = -26 * GetDeviceCaps(hdc, LOGPIXELSY) / 72;
				ReleaseDC(NULL, hdc);
				lf.lfWeight = FW_BOLD;
				lf.lfQuality = ANTIALIASED_QUALITY;
				HFONT hFont = CreateFontIndirect(&lf);

				SendDlgItemMessage(hDlg, IDC_LABEL_ALTITUDE, WM_SETFONT, (WPARAM)hFont, 0);
 
				// Start a timer to update the altimeter reading
				SetTimer(hDlg, 1, 500, NULL);
            }
            return (INT_PTR)TRUE;

		case WM_INITMENUPOPUP:
			// The menu is about to popup so enable/disable
			// the various menu items depending upon the state
			// of the application.
			if (GPS_IsOpened())
			{
				EnableMenuItem((HMENU)wParam, IDM_GPS_START, MF_BYCOMMAND | MF_GRAYED);
				EnableMenuItem((HMENU)wParam, IDM_GPS_STOP,  MF_BYCOMMAND | MF_ENABLED);
			}
			else
			{
				EnableMenuItem((HMENU)wParam, IDM_GPS_START, MF_BYCOMMAND | MF_ENABLED);
				EnableMenuItem((HMENU)wParam, IDM_GPS_STOP,  MF_BYCOMMAND | MF_GRAYED);
			}
			break;


        case WM_COMMAND:
            switch (LOWORD(wParam))
			{
				case IDOK:
		            EndDialog(hDlg, LOWORD(wParam));
			        return (INT_PTR)TRUE;

				case IDM_GPS_START:
					if (!GPS_IsOpened())
					{
						GPS_Open();
					}
					break;
           
				case IDM_GPS_STOP:
					if (GPS_IsOpened())
					{
						GPS_Close();
					}
					break;
            }
            break;

		case WM_TIMER:
			// Check if the GPS has updated state or position
			// information available
			if (GPS_DataHasChanged())
			{
				GPS_POSITION pos;
				GPS_DEVICE device;
				WCHAR szBuffer[2048], szBuffer2[128];

				// Get the current GPS location information
				GPS_GetData(&pos, &device);

				// Format the GPS location information into
				// a status message
				swprintf(szBuffer, L"%s %s %s\r\n",
					device.szGPSFriendlyName,
					GPS_GetServiceStateDescription(device.dwServiceState),
					GPS_GetServiceStateDescription(device.dwDeviceState));

				if (pos.dwValidFields & GPS_VALID_LATITUDE)
				{
					swprintf(szBuffer2, L"Latitude (DD):\r\n   %f\r\n", pos.dblLatitude);
					wcscat(szBuffer, szBuffer2);

					wcscat(szBuffer, L"Latitude (D,M,S):\r\n   ");
					GPS_FormatDegreesMinutesSeconds(szBuffer2, pos.dblLatitude);
					wcscat(szBuffer, szBuffer2);
					wcscat(szBuffer, L"\r\n");
				}
	
				if (pos.dwValidFields & GPS_VALID_LONGITUDE)
				{
					swprintf(szBuffer2, L"Longitude (DD):\r\n   %f\r\n", pos.dblLongitude);
					wcscat(szBuffer, szBuffer2);

					wcscat(szBuffer, L"Longitude (D,M,S):\r\n   ");
					GPS_FormatDegreesMinutesSeconds(szBuffer2, pos.dblLongitude);
					wcscat(szBuffer, szBuffer2);
					wcscat(szBuffer, L"\r\n");
				}

				if ((pos.dwValidFields & GPS_VALID_SATELLITES_USED_PRNS) &&
                       (pos.dwValidFields & GPS_VALID_SATELLITES_IN_VIEW) &&
					(pos.dwValidFields & GPS_VALID_SATELLITE_COUNT))
				{
					int iSatellitesInSolution = 0;
					for (int i = 0; i < pos.dwSatelliteCount; i++)
					{
						for (int j = 0; j < pos.dwSatellitesInView; j++)
						{
							if (pos.rgdwSatellitesUsedPRNs[i] == pos.rgdwSatellitesInViewPRNs[j])
							{
								iSatellitesInSolution++;
								break;
							}
						}
					}

					swprintf(szBuffer2, L"Satellite Count:\r\n   %d/%d (%d)\r\n",
						iSatellitesInSolution,
						pos.dwSatellitesInView,
						pos.dwSatelliteCount);
					wcscat(szBuffer, szBuffer2);
				}

				if (pos.dwValidFields & GPS_VALID_UTC_TIME)
				{
					wcscat(szBuffer, L"Time:\r\n   ");

					GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &pos.stUTCTime, NULL, szBuffer2, sizeof(szBuffer2) / sizeof(szBuffer2[0])); 
					wcscat(szBuffer, szBuffer2);

					wcscat(szBuffer, L" ");

					GetTimeFormat(LOCALE_USER_DEFAULT, 0, &pos.stUTCTime, NULL, szBuffer2, sizeof(szBuffer2) / sizeof(szBuffer2[0])); 
					wcscat(szBuffer, szBuffer2);

					wcscat(szBuffer, L"\r\n");
				}

				// Update the status textbox
				SetDlgItemText(hDlg, IDC_EDIT_STATUS, szBuffer);

				// Update the speed label if we have
				// a valid speed reading
				if (pos.dwValidFields & GPS_VALID_ALTITUDE_WRT_SEA_LEVEL)
				{
					// Update the altitude reading
					swprintf(szBuffer, L"%0.2fft", pos.flAltitudeWRTSeaLevel);
					SetDlgItemText(hDlg, IDC_LABEL_ALTITUDE, szBuffer);

					// Update the altitude pointer
					RECT rcBounds;
					HWND hWndPointer;

					hWndPointer = GetDlgItem(hDlg, IDC_BITMAP_POINTER);
					GetClientRect(hWndPointer, &rcBounds);
					MapWindowPoints(hWndPointer, hDlg, (LPPOINT)&rcBounds, 2);

					if (pos.flAltitudeWRTSeaLevel >= 0 && pos.flAltitudeWRTSeaLevel <= 180)
						rcBounds.top = 173 - (int)pos.flAltitudeWRTSeaLevel;
					else
						rcBounds.top = 173;

					SetWindowPos(hWndPointer, NULL, rcBounds.left, rcBounds.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
				}
			}
			break;

        case WM_CLOSE:
			KillTimer(hDlg, 1);

			if (GPS_IsOpened())
			{
				GPS_Close();
			}

			EndDialog(hDlg, message);
            return (INT_PTR)TRUE;
    }

    return (INT_PTR)FALSE;
}

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPTSTR    lpCmdLine,
                   int       nCmdShow)
{
	return DialogBox(hInstance, (LPCTSTR)IDD_MOBILEALTIMETER, NULL, MobileAltimeterDialog);
}
